package cn.ad.server.web.utils;


import org.springframework.stereotype.Component;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * @author dongbin.yu
 * @from 2016-07-11
 * @since V1.0
 */
@Component
public class TimeTracker {

    private ThreadLocal<ConcurrentMap<String,TimeSlice>> timeTracker = new ThreadLocal<>();

    private BlockingQueue<ConcurrentMap<String, TimeSlice>> timeQueue = new ArrayBlockingQueue<>(10);

    public void start(String trackName){

        ConcurrentMap<String, TimeSlice> timeSliceConcurrentMap = timeTracker.get();
        if (timeSliceConcurrentMap == null) {
            timeSliceConcurrentMap = new ConcurrentHashMap<>();
            TimeSlice timeSlice = new TimeSlice();
            timeSlice.setStartTime(System.currentTimeMillis());
            timeSliceConcurrentMap.put(trackName, timeSlice);
        } else {
            TimeSlice timeSlice = timeSliceConcurrentMap.get(trackName);
            if (timeSlice != null) {
                timeSlice.setStartTime(System.currentTimeMillis());
            } else {
                timeSlice = new TimeSlice();
                timeSlice.setStartTime(System.currentTimeMillis());
            }
            timeSliceConcurrentMap.put(trackName, timeSlice);
        }

        timeTracker.set(timeSliceConcurrentMap);
    }

    public void end(String trackName){
        ConcurrentMap<String, TimeSlice> timeSliceConcurrentMap = timeTracker.get();
        if (timeSliceConcurrentMap != null) {
            TimeSlice timeSlice = timeSliceConcurrentMap.get(trackName);
            if (timeSlice != null) {
                timeSlice.setTime(System.currentTimeMillis() - timeSlice.getStartTime());
            }
        }
    }

    public void add(String trackName) {

        ConcurrentMap<String, TimeSlice> timeSliceConcurrentMap = timeTracker.get();
        if (timeSliceConcurrentMap != null) {
            TimeSlice timeSlice = timeSliceConcurrentMap.get(trackName);
            if (timeSlice != null) {
                timeSlice.setTime(timeSlice.getTime() + (System.currentTimeMillis() - timeSlice.getStartTime()));
            }
        }
    }

    public void offer() {

        ConcurrentMap<String, TimeSlice> timeSliceConcurrentMap = timeTracker.get();
        if (timeSliceConcurrentMap != null) {
            if (!timeQueue.offer(timeSliceConcurrentMap)) {
                timeQueue.poll();
                timeQueue.offer(timeSliceConcurrentMap);
            }
            timeTracker.remove();
        }
    }

    private class TimeSlice{

        private long startTime;

        private long time;

        public long getStartTime() {
            return startTime;
        }

        public void setStartTime(long startTime) {
            this.startTime = startTime;
        }

        public long getTime() {
            return time;
        }

        public void setTime(long time) {
            this.time = time;
        }
    }

}
